#include "minimp3_demuxer.h"

namespace OHOS {
namespace Media {
namespace Plugin {

Minimp3Demuxer::Minimp3Demuxer(std::string name)
    : name_(std::move(name)),
      callback_(nullptr),
      allocator_(std::make_shared<DemuxerPluginAllocator>()),
      mediaInfo_(nullptr),
      selectedTrackIds_()
{
    MEDIA_LOG_I("ctor called, plugin name: %s", name_.c_str());
}

Status Minimp3Demuxer::Init()
{
    // 做初始化的工作
    // 初始化那些播放任意音频流都需要用的资源
}

Status Minimp3Demuxer::Prepare()
{
    // 启动播放某一条音频流之前会调用
    // 做播放前的准备工作
    // 比如设置一些参数
    // 这些参数可能是播放该流之前，框架设置下来的。
}

Status Minimp3Demuxer::Start()
{
    // 启动播放
    // 调用minimp3的接口，使得它启动解码工作
}

Status Minimp3Demuxer::Stop()
{
    // 停止播放
    // 调用minimp3的停止解码接口
}

Status Minimp3Demuxer::SetDataSource(const std::shared_ptr<DataSource> &source)
{
    dataSource_ = source;
    return Status::OK;
}
Status Minimp3Demuxer::GetMediaInfo(MediaInfo &mediaInfo)
    // 参考 Markdown 文档中说明的要解析的信息
    dataSource_->ReadAt(offset, length, buffer);
    // call minimp3 function (buffer) -> mediaInfo
    /*
        MetaID::MIME,
        MetaID::STREAM_INDEX,
        MetaID::MEDIA_CODEC_CONFIG,
        MetaID::MEDIA_BITRATE,
        MetaID::AUDIO_CHANNELS,
        MetaID::AUDIO_SAMPLE_RATE,
        MetaID::AUDIO_SAMPLE_FORMAT,
        MetaID::AUDIO_SAMPLE_PRE_FRAME,
        MetaID::AUDIO_CHANNEL_LAYOUT,
        MetaID::AUDIO_MPEG_VERSION,
        MetaID::AUDIO_MPEG_LAYER,
    */
}
Status Minimp3Demuxer::ReadFrame(Buffer &buffer, int32_t timeOutMs)
{
    // 调用minimp3的接口解析出一帧数据
    dataSource_->ReadAt(offset, length, inputBuffer);
    // call minimp3 function (inputBuffer, out to pkt.data)
    
    // 假设解析出的 EsData 数据在 pkt.data 中

    // 把数据存入buffer中
    auto data = buffer.AllocMemory(allocator_, frameSize);
    if (data) {
        size_t writeSize = data->Write(pkt.data, frameSize); // pkt.data中是真正的数据
        ASSERT_CONDITION(writeSize == frameSize, "Copy data failed.");
    }
    return data != nullptr ? Status::OK : Status::ERROR_UNKNOWN;
}

Status Minimp3Demuxer::SeekTo(int32_t trackId, int64_t timeStampUs, SeekMode mode)
{
    // 调用 minimp3 的 seek 函数
}

size_t Minimp3Demuxer::GetTrackCount()
{
    size_t trackCnt = 0;
    if (mediaInfo_) {
        trackCnt = mediaInfo_->tracks.size();
    }
    return trackCnt;
}
Status Minimp3Demuxer::SelectTrack(int32_t trackId)
{
    if (!mediaInfo_) {
        MEDIA_LOG_E("SelectTrack called before GetMediaInfo()...");
        return Status::ERROR_INVALID_DATA;
    }
    if (trackId < 0 || trackId >= static_cast<int32_t>(mediaInfo_->tracks.size())) {
        MEDIA_LOG_E("SelectTrack called with invalid trackId: %d, number of tracks: %d", trackId,
                    static_cast<int>(mediaInfo_->tracks.size()));
        return Status::ERROR_INVALID_DATA;
    }
    OSAL::ScopedLock lock(mutex_);
    auto it = std::find_if(selectedTrackIds_.begin(), selectedTrackIds_.end(),
                           [trackId](int32_t streamId) { return trackId == streamId; });
    if (it == selectedTrackIds_.end()) {
        selectedTrackIds_.push_back(trackId);
    }
    return Status::OK;
}
Status Minimp3Demuxer::UnselectTrack(int32_t trackId)
{
    OSAL::ScopedLock lock(mutex_);
    auto it = std::find_if(selectedTrackIds_.begin(), selectedTrackIds_.end(),
                           [trackId](int32_t streamId) { return trackId == streamId; });
    if (it != selectedTrackIds_.end()) {
        selectedTrackIds_.erase(it);
    }
    return Status::OK;
}
Status Minimp3Demuxer::GetSelectedTracks(std::vector<int32_t> &trackIds)
{
    OSAL::ScopedLock lock(mutex_);
    trackIds = selectedTrackIds_;
    return Status::OK;
}

void* Minimp3Demuxer::DemuxerPluginAllocator::Alloc(size_t size)
{
    return static_cast<void*>(new (std::nothrow) uint8_t[size]);
}

void Minimp3Demuxer::DemuxerPluginAllocator::Free(void* ptr)
{
    if (ptr) {
        auto data = static_cast<uint8_t*>(ptr);
        delete[] data;
    }
}


}
}
}